﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Sunny.Entity;
using Sunny.Model.RequestParam;
using Sunny.Model.Vo;
using Sunny.Util.Exception;

namespace Sunny.Service
{
    public class DeptService
    {
        private readonly SunnyContext _sunnyContext;

        public DeptService(SunnyContext sunnyContext)
        {
            _sunnyContext = sunnyContext;
        }

        public async Task<List<DeptTreeVo>> GetDeptTree()
        {
           
            var depts = await  _sunnyContext.SysDepts.OrderBy(t=>t.OrderNum).ToListAsync();
            
            return BuildDeptTree(depts,0);
            
        }

        private List<DeptTreeVo> BuildDeptTree(List<SysDept> depts,long parentId)
        {
            List<DeptTreeVo> deptTreeVos = new List<DeptTreeVo>();
            
            var currentDepts = depts.Where(t=>t.ParentId == parentId);
            foreach (var currentDept in currentDepts)
            {
                DeptTreeVo deptTreeVo = new DeptTreeVo();
                deptTreeVo.Id = currentDept.DeptId;
                deptTreeVo.Label = currentDept.DeptName;
                deptTreeVo.Children = BuildDeptTree(depts,currentDept.DeptId);
                deptTreeVos.Add(deptTreeVo);
            }
            return deptTreeVos;
        }

        public async Task<RoleDeptTreeSelectVo> RoleDeptTreeSelect(long roleId)
        {
            RoleDeptTreeSelectVo roleDeptTreeSelectVo = new RoleDeptTreeSelectVo();
            var checkedKeys = await _sunnyContext.SysRoleDepts.Where(t=>t.RoleId == roleId).Select(t=>t.DeptId).ToListAsync();
            roleDeptTreeSelectVo.CheckedKeys =checkedKeys;
            roleDeptTreeSelectVo.Depts = await this.GetDeptTree();
            return roleDeptTreeSelectVo;
        }

        public async Task<List<SysDept>> List(DeptListParam param)
        {
            var depts = _sunnyContext.SysDepts.AsQueryable();
            if(!string.IsNullOrEmpty(param.DeptName))
            {
                depts = depts.Where(t=>t.DeptName.Contains(param.DeptName));
            }
            if(!string.IsNullOrEmpty(param.Status))
            {
                depts = depts.Where(t=>t.Status == param.Status);
            }
            
            var deptList = await depts.OrderBy(t=>t.OrderNum).ToListAsync();
            return deptList;
        }

        public async Task Add(SysDept sysDept)
        {
            var parentDept = await _sunnyContext.SysDepts.SingleOrDefaultAsync(t=>t.DeptId == sysDept.ParentId);
            sysDept.Ancestors = parentDept.Ancestors+","+ sysDept.ParentId;
            await _sunnyContext.SysDepts.AddAsync(sysDept);
            await _sunnyContext.SaveChangesAsync();
        }

        public async Task<SysDept> GetById(long deptId)
        {
            return await _sunnyContext.SysDepts.SingleOrDefaultAsync(t=>t.DeptId == deptId);
        }

        public async Task Update(SysDept sysDept)
        {
           var dept = await _sunnyContext.SysDepts.SingleOrDefaultAsync(t=>t.DeptId == sysDept.DeptId);
           var parentDept = await _sunnyContext.SysDepts.SingleOrDefaultAsync(t=>t.DeptId == sysDept.ParentId);
           // dept.Ancestors
           dept.DeptName = sysDept.DeptName;
           dept.Email = sysDept.Email;
           dept.Leader = sysDept.Leader;
           dept.OrderNum = sysDept.OrderNum;
           dept.ParentId = sysDept.ParentId;
           dept.Phone = sysDept.Phone;
           dept.Status = sysDept.Status;
           dept.Ancestors = parentDept.Ancestors+","+dept.ParentId;

           await _sunnyContext.SaveChangesAsync();
        }

        public async Task Delete(long deptId)
        {
            var hasChildren = await _sunnyContext.SysDepts.AnyAsync(t=>t.ParentId == deptId);
            if(hasChildren)
            {
                throw new BusinessException(CodeMessage.DeptHasChild);
            }
            var hasUser = await _sunnyContext.SysUsers.AnyAsync(t=>t.DeptId == deptId);
            if(hasUser)
            {
                throw new BusinessException(CodeMessage.DeptHasUser);
            }
            SysDept sysDept = new SysDept(){DeptId =  deptId};
            _sunnyContext.Attach(sysDept).State = EntityState.Deleted;
            await _sunnyContext.SaveChangesAsync();
        }

        public async Task<string> GetDeptAllLevelName(long deptId)
        {
            var dept = await _sunnyContext.SysDepts.SingleOrDefaultAsync(t=>t.DeptId == deptId);
            if(dept != null)
            {
                var deptIds = Array.ConvertAll(dept.Ancestors.Split(","),long.Parse);
                var deptNames = await _sunnyContext.SysDepts.Where(t=>deptIds.Contains(t.DeptId) || t.DeptId == deptId).OrderBy(t=>t.DeptId).Select(t=>t.DeptName).ToListAsync();
                return string.Join("/",deptNames);
            }
            return "";
        }
        
    }
}